package ci.web.router;

import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;

import java.net.URL;

import ci.web.core.CiContext;

/**
 * 路由中心<br/>
 * 请求拦截器<br/>
 * 静态文件路由<br/>
 * CiHandler脚本路由<br/>
 * @author zhh
 */
public class CiRouter implements CiCall{

    private static InternalLogger logger = InternalLoggerFactory.getInstance(CiRouter.class);
    
    private CiFile file;
    //脚本-动态添加类
    private CiScaner scaner;
    //拦截器
    private CiCall filter;
    
    
    public CiRouter() {
        file = new CiFile("www");
        scaner = new CiScaner();
    }
    /**
     * 设置静态文件路由
     * @param dir			磁盘文件目录
     * @param path			http请求路由路径
     * @param maxAge		静态文件缓存时间(秒)
     * @param exceptExtend	排除的文件后缀
     */
    public void setFile(String dir, String path, int maxAge, String exceptExtend){
    	if(dir.isEmpty() && path.isEmpty()){
    		return;
    	}
        file = new CiFile(dir, path, maxAge, exceptExtend);
    }
    /**
     * 设置静态文件路由
     * @param f
     */
    public void setFile(CiFile f){
        if(f!=null){
            file = f;
        }
    }
    /**
     * 获取静态文件路由
     * @return
     */
    public CiFile getFile(){
        return file;
    }
    
    /**
     * 获取filter
     * @return
     */
    public CiCall getFilter(){
        return filter;
    }
    /**
     * 设置filter
     * @param r
     */
    public void setFilter(CiCall r){
        filter = r;
    }
    
    /**
     * 设置脚本扫描器
     * @param dir           扫描路径
     * @param packageName   扫描限定包
     */
    public void setHandler(String dir, String packageName){
        scaner = new CiScaner(dir, packageName, scaner.handlers());
    }
    /**
     * 获取脚本扫描器
     * @return
     */
    public CiScaner getHandler(){
        return scaner;
    }
    
    /**
     * 直接添加脚本实现类
     * @param clazz
     */
    public void add(Class<?> clazz){
        scaner.add(clazz);
    }
    
    /**
     * call
     * @param ctx
     * @return
     * @throws Exception
     */
    public boolean call(CiContext ctx) throws Exception{
        try{
            if(filter!=null && filter.call(ctx)){
                return true;
            }
            if(file!=null && file.match(ctx)){
                return file.call(ctx);
            }
            CiHandler wrap = scaner.get(ctx);
            if(wrap!=null){
                return wrap.call(ctx);
            }
        }catch(Exception e){
            ctx.out().setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR);
//            logger.error("call", e);
            StackTraceElement[] arr = e.getCause().getStackTrace();
            StringBuilder sb = new StringBuilder();
            for(StackTraceElement s:arr){
                //sun.reflect.NativeMethodAccessorImpl
                if(s.getClassName().startsWith("sun.")){
                    break;
                }
                sb.append(s).append('\n');
            }
            logger.error(sb.toString());
            return true;
        }
        return false;
    }
    /**
     * 脚本扫描路径URL
     * @return
     */
    public URL[] urls(){
        return scaner.urls();
    }
    /**
     * 重新扫描脚本
     */
    public synchronized void reload() {
       this.scaner = new CiScaner(scaner.dir(), scaner.packageName(), scaner.handlers());
    }
    
}
